#include <game/flow/EntryDefinition.h>
#include <game/ScreenReferenceDefinition.h>
#include <game/flow/EntryExitDefinition.h>

#include <xml/Stream.h>
#include <Gluck.h>
#include <system/assert.h>

ARELLO_GAME_NAMESPACE_DECL_START
namespace flow {

EntryDefinition::EntryDefinition()
{
}

EntryDefinition::~EntryDefinition()
{
}

bool EntryDefinition::on_attribute(xml::Provider * prov, const std::string & name, const std::string & value)
{
	if (name == "Name")
	{
		this->name = value;
		return true;
	}

	return false;
}

class SelectorClassLoader
	: public xml::ObjectANSI
{
public:
	virtual bool on_attribute(xml::Provider * prov, const std::string & name, const std::string & value)
	{
		if (name == "Name")
			return converter::convert(value, &this->name);

		return false;
	}

	const std::string& GetName() 
	{
		return this->name;
	}
private:
	std::string name;
};

bool EntryDefinition::on_node(xml::Provider * prov, const std::string & name)
{
	if (name == "Screen")
	{
		ScreenReferenceDefinition def;
		if (!prov->parse_object(def.GetLoader()))
			return false;

		this->screenReference = def.ReleaseScreenReference();
		assertSelectorMode();
		return true;
	}
	if (name == "Selector")
	{
		SelectorClassLoader loader;

		if (!prov->parse_object(&loader))
			return false;
		
		this->selectorClass = loader.GetName();
		assertSelectorMode();
		return true;
	}
	if (name == "Exit")
	{
		std::auto_ptr<EntryExitDefinition> localExit(new EntryExitDefinition());
		if (!prov->parse_object(localExit->GetLoader()))
			return false;

		this->exits.push_back(localExit.release());
		assertSelectorMode();
		return true;
	}

	return false;
}

void EntryDefinition::assertSelectorMode()
{
	if (!this->selectorClass.empty())
		LIBA_ASSERT(!this->screenReference.get());
}

ScreenReference* EntryDefinition::GetScreenReference()
{
	return this->screenReference.get(); 
}

} // namespace flow
ARELLO_GAME_NAMESPACE_DECL_END